import time

import yaml
from faker.proxy import Faker
from gevent import monkey;monkey.patch_all()
import json
import random
import gevent
import requests

from gevent.pool import Pool
from datetime import datetime, timedelta
from collections import defaultdict




with open("D:\SaasFoodLimit\config.yml", "r", encoding="utf-8") as f:
    config = yaml.load(f, Loader=yaml.FullLoader)

# 原子计数器（gevent协程安全）
class AtomicCounter:
    def __init__(self):
        self.value = 0
        self._lock = gevent.lock.Semaphore()

    def increment(self):
        with self._lock:
            self.value += 1


# 全局统计
success_counter = AtomicCounter()
fail_counter = AtomicCounter()
error_records = defaultdict(AtomicCounter)


def order_request(equipmentId,  equipmentName, equipmentSn, equipmentType, equipmentTypeName):
    header = config["header"]
    def log_failure(step, error):
        fail_counter.increment()
        error_records[step].increment()
        print(f"❌ 失败接口 {step}: {error}")
    digits = '0123456789'
    tomorrow = datetime.now() + timedelta(days=config["day"])

    #下单
    try:
        data = {
            "canteenId": "1807951831235153922",
            "canteenName": "田庆测试食堂",
            "deliveryMode": "1",
            "handleBy": "stgly7",
            "handleById": "1807952536436068353",
            "machineInfo": {
                "machineId": equipmentId,
                "machineName": equipmentName,
                "machineSn": equipmentSn,
                "machineType": equipmentType,
                "machineTypeName": equipmentTypeName
            },
            "orderInfoList": [
                {
                    "diningTime": tomorrow.strftime("%Y-%m-%d")+" 22:00:00",
                    "machineCreateDate": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    "mealId": "3356",
                    "mealLicenseId": "3352",
                    "mealName": "夜宵",
                    "netStatus": "online",
                    "orderInfoItem": [
                        {
                            "licenseId": "7594",
                            "lunchBoxFee": "",
                            "mealFlag": 0,
                            "payableAmount": "10.00",
                            "price": "10.00",
                            "productName": "辣炒花蛤",
                            "productNumber": 1,
                            "productPic": "",
                            "productSn": "102120",
                            "productSpuId": "7594",
                            "remarks": "",
                            "stallId": "1807951900709605378",
                            "stallName": "pos档口",
                            "unit": 0,
                            "weighFlag": 0,
                            "weight": 0,
                            "weightPerUnit": ""
                        }
                    ],
                    "orderSource": "machine",
                    "payableAmount": "10.00",
                    "remarks": "",
                    "sellMode": "order"
                }
            ],
            "orderPay": {
                "cardChipNo": "",
                "otherPaymentModeId": "",
                "otherPaymentModeName": "",
                "paymentMedium": "cash",
                "paymentMode": "CASH"
            },
            "uniqueNo": ''.join(random.choices(digits, k=20))
            }
        resp = requests.post(
            url="https://testsaasapi.keyijievip.com/order/api/hand-held-pos/reserve-order-submit",
            headers=header,
            json=data,
            timeout=5
        )
        resp.raise_for_status()
        print("✅ 提交订单成功", resp.json())
        if resp.json().get("code") != 0:
            log_failure("提交订单", resp.json().get("msg", "未知业务错误"))
            return
    except Exception as e:
        log_failure("提交订单", str(e))
        return

    # 全部成功
    success_counter.increment()


# 最终统计输出
def print_statistics():
    print("\n📊 压力测试结果:")
    print(f"✅ 成功请求: {success_counter.value}")
    print(f"❌ 失败请求: {fail_counter.value}")
    print("🔧 错误分布:")
    for step, counter in error_records.items():
        print(f"  {step}: {counter.value}次失败")


if __name__ == "__main__":
    # 初始化测试数据
    url= "https://testsaasapi.keyijievip.com/terminal/equipment/page?equipmentName=&equipmentSn=&equipmentTypeName=&onlineStatus=&current=1&size=10&descs=&ascs="
    header = config["header"]
    data = {"deptIds":["1807951831235153922"],"expireDate":[],"memberCategoryIds":[],"cardTypeIds":[],"memberIds":[],"statusGroup":[0,1],"expired":False,"memberDeptId":"1802569625167716353","current":1,"size":10,"descs":"","ascs":""}
    #查询用户数据
    response = requests.get(url,headers=header,data=json.dumps(data))
    print("测试数据查询完成")
    equipmentId_list = []
    equipmentName_list = []
    equipmentSn_list= []
    equipmentType_list=[]
    equipmentTypeName_list=[]
    if response.ok:
        try:
            response_data = response.json()
            records = response_data.get('data', {}).get('records', [])

            # 只取前5个记录
            for i, record in enumerate(records):
                if i >= config["number"]:  # 只处理前10条记录
                    break

                if 'equipmentId' in record:
                    equipmentId_list.append(record['equipmentId'])
                if 'equipmentName' in record:
                    equipmentName_list.append(record['equipmentName'])
                if 'equipmentSn' in record:
                    equipmentSn_list.append(record['equipmentSn'])
                if 'equipmentType' in record:
                    equipmentType_list.append(record['equipmentType'])
                if 'equipmentTypeName' in record:
                    equipmentTypeName_list.append(record['equipmentTypeName'])
        except (ValueError, TypeError) as e:
            print(f"⚠️ JSON解析错误: {str(e)}")
    else:
        print(f"⚠️ API请求失败: HTTP {response.status_code} - {response.reason}")
    print(equipmentId_list)
    # member_ids = [m["memberId"] for m in member_ids_list]
    # 创建协程池
    pool = Pool(config["number"])
    jobs = [pool.spawn(order_request, equipmentId,  equipmentName, equipmentSn, equipmentType, equipmentTypeName) for equipmentId,  equipmentName, equipmentSn, equipmentType, equipmentTypeName in zip(equipmentId_list, equipmentName_list, equipmentSn_list, equipmentType_list, equipmentTypeName_list)]
    gevent.joinall(jobs)

    # 输出统计结果
    print_statistics()